package com.erp.framework.controller.form;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;

import org.apache.commons.beanutils.PropertyUtils;

import com.erp.framework.SimpleConstants;
import com.erp.framework.util.CopyUtil;
import com.erp.framework.util.logger.Logger;

//public class MultiInputForm extends SimpleUserStyleForm {
public class MultiInputForm extends SimpleCoreForm {

    protected ArrayList multiRows = new ArrayList();

    protected Class multiRowClazz;

    protected String idx[];
    protected String rowMode[];
    protected String isDelete[];
    protected int sidx = 0;

    public MultiInputForm() {

    }
    
    public String getDeleteIdx() {

        return null;
    }

    public MultiInputForm(Class cMultiRowClazz) {

        this.multiRowClazz = cMultiRowClazz;
    }

    public void setMultiRows(ArrayList multiRows) {

        this.multiRows = multiRows;
    }

    public void setMultiRowClazz(Class multiRowClazz) {

        this.multiRowClazz = multiRowClazz;
    }

    public void setIdx(String[] idx) {

        this.idx = idx;
    }

    public void setRowMode(String[] rowMode) {

        this.rowMode = rowMode;
    }

    public void setIsDelete(String[] isDelete) {

        this.isDelete = isDelete;
    }

    public void setSidx(int sidx) {

        this.sidx = sidx;
    }

    public ArrayList getMultiRows() {

        if (this.multiRows.size() > 0) {
            return this.multiRows;
        } else {
            return getRows();
        }
    }

    public String[] getIdx() {

        return this.idx;
    }

    public String[] getRowMode() {

        return this.rowMode;
    }

    public String[] getIsDelete() {

        return this.isDelete;
    }

    public int getSidx() {

        return sidx;
    }

    public void addRow() {

        try {
            this.multiRows = getRows();
            Object mRow = this.multiRowClazz.newInstance();
            PropertyUtils.setSimpleProperty(mRow, "idx", Integer.toString(this.multiRows.size()));
            PropertyUtils.setSimpleProperty(mRow, "rowMode", ROW_MODE_CREATE);
            
            PropertyUtils.setSimpleProperty(mRow, "ts", this.ts);
            PropertyUtils.setSimpleProperty(mRow, "tsName", this.tsName);
            
            this.multiRows.add(mRow);
        } catch (Exception e) {
            if (Logger.isDebugLevel()) {
                Logger.logExceptions(this, e);
            }
        }
    }

    public void addRow(Object defaultValueObj) {

        try {
            this.addRow();
            Object mRow = this.multiRowClazz.newInstance();
            CopyUtil cpUtil = new CopyUtil();
            cpUtil.convToStrObj(mRow, defaultValueObj);
            //todo: need to handle the ts object, later
            //PropertyUtils.setSimpleProperty(mRow, "ts", this.ts);
            //PropertyUtils.setSimpleProperty(mRow, "tsName", this.tsName);
            
            this.setRow(this.getMultiRows().size() - 1, mRow);
        } catch (Exception e) {
            if (Logger.isDebugLevel()) {
                Logger.logExceptions(this, e);
            }
        }
    }

    public void deleteRow(int delIdx) {

        try {
            this.multiRows = getRows();
            Object row = multiRows.get(delIdx);
            PropertyUtils.setSimpleProperty(row, "isDelete", "checked");
            multiRows.set(delIdx, row);
        } catch (Exception e) {
            if (Logger.isDebugLevel()) {
                Logger.logExceptions(this, e);
            }
        }
    }

    public ArrayList getFinalRows() {

        return getRows();
    }

    protected ArrayList getRows() {

        try {
            if (idx == null)
                return multiRows;

            // Get the mapping first
            int[] mapping = new int[idx.length];
            for (int i = 0; i < idx.length; i++) {
                mapping[i] = Integer.parseInt(idx[i]);
            }

            PropertyDescriptor fields[] = PropertyUtils.getPropertyDescriptors(this);
            for (int i = 0; i < fields.length; i++) {
                String name = fields[i].getName();
                if (fields[i].getPropertyType() != null && fields[i].getPropertyType().isArray() && !name.equals("isDelete")) {
                    Object values[] = (Object[]) PropertyUtils.getSimpleProperty(this, name);
                    if (values != null) {
                        for (int j = 0, k = -1; j < values.length; j++) {
                            try {
                                k = mapping[j];
                                if (k > multiRows.size() - 1) {
                                    Logger.all(this, "getRows(), !!!! Should never happen! [property='" + name + "(" + j
                                            + ")', " + k + "/" + multiRows.size() + "]");
                                } else {
                                    try {
                                        MultiRow mRow = (MultiRow) multiRows.get(k);
                                        PropertyUtils.setSimpleProperty(mRow, name, values[j]);
                                        multiRows.set(k, mRow);
                                    } catch (Exception e) {
                                    }
                                }
                            } catch (Exception e) {
                                if (Logger.isDebugLevel()) {
                                    Logger.logExceptions(this, e);
                                }
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < multiRows.size(); i++) {
                PropertyUtils.setSimpleProperty(multiRows.get(i), "isDelete", "");
            }

            if (this.isDelete != null) {
                Logger.debug(this, "getRows(), size of delete array = " + isDelete.length);
                for (int i = 0, delIdx; i < this.isDelete.length; i++) {
                    delIdx = Integer.parseInt(this.isDelete[i]);
                    Object row = multiRows.get(delIdx);
                    PropertyUtils.setSimpleProperty(row, "isDelete", "checked");
                    multiRows.set(delIdx, row);
                }
            }
        } catch (Exception e) {
            if (Logger.isDebugLevel()) {
                Logger.logExceptions(this, e);
            }
        }
        return multiRows;
    }

    public void setRow(int idx, Object mRow) {

        try {
            PropertyUtils.setSimpleProperty(mRow, "idx", Integer.toString(idx));
            if (idx > this.multiRows.size() - 1) {
                this.multiRows.add(mRow);
            } else {
                this.multiRows.set(idx, mRow);
            }
        } catch (Exception e) {
            if (Logger.isDebugLevel()) {
                Logger.logExceptions(this, e);
            }
        }
    }

    private Field[] fieldsMerge(Field[] f1, Field[] f2) {

        Field[] fields = null;
        try {
            fields = new Field[f1.length + f2.length];
            int fIdx = 0;
            for (int i = 0; i < f1.length; i++) {
                fields[fIdx] = f1[i];
                fIdx++;
            }
            for (int j = 0; j < f2.length; j++) {
                fields[fIdx] = f2[j];
                fIdx++;
            }
        } catch (Exception e) {
            if (Logger.isDebugLevel()) {
                Logger.logExceptions(this, e);
            }
        }
        return fields;
    }

    public int getTotalPage() {

        int tPage = (int) (multiRows.size() / SimpleConstants.MAX_DISPLAY);
        if (multiRows.size() % SimpleConstants.MAX_DISPLAY != 0)
            tPage += 1;
        return tPage;
    }

    public int getCurrentPage() {

        int cPage = (int) ((sidx + 1) / SimpleConstants.MAX_DISPLAY);
        if ((sidx + 1) % SimpleConstants.MAX_DISPLAY != 0)
            cPage += 1;
        return cPage;
    }

    public String getLastPageSidx() {

        return String.valueOf(multiRows.size() - SimpleConstants.MAX_DISPLAY);
    }

}